﻿Imports System.IO
Imports System.IO.Packaging
Namespace Utilities
    Public Class ZipFolder
        'Add a references to System.IO.Compression, System.IO.Compression.FileStream




        Public Shared Function CreateZipFromFolder(ZipFullFilename As String, FolderPath As String, Optimization As CompressionOption) As String
            'Returns status message to display
            Try
                'Ensure FolderPath is not a relative path
                If (FolderPath.Trim().Length < 4) OrElse (FolderPath.Substring(1, 1) <> ":") Then
                    Throw New IO.DirectoryNotFoundException(" Error: Not Absolute Folder Path: " & FolderPath)
                End If

                If IO.Directory.Exists(FolderPath) = False Then _
                    Throw New IO.DirectoryNotFoundException(" CreateZipFromFolder: Error: " & FolderPath)

                If IO.File.Exists(ZipFullFilename) Then _
                    IO.File.Delete(ZipFullFilename)

                'Get list of files in directory tree from FolderPath down
                'Note: Does not capture an empty folder
                Dim files() = IO.Directory.GetFiles(FolderPath, "*.*", SearchOption.AllDirectories)
                If FolderPath.EndsWith("\") Then FolderPath = FolderPath.Substring(0, FolderPath.Length - 1)

                Using Zip As Package = ZipPackage.Open(ZipFullFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite)
                    For Each item In files
                        Dim relFile = item.Substring(FolderPath.Length)
                        AddFileToZip(Zip, item, relFile, Optimization)
                    Next
                End Using
            Catch ex As Exception
                Throw New Exception("ExtractZipToFolder: Error: " & ex.Message, ex)
            End Try
            Dim message = String.Format("Created zip file: {0} from folder {1}", ZipFullFilename, FolderPath)
            Return message
        End Function

        Private Shared Sub AddFileToZip(ByVal Zip As Package, ByVal FullFilename As String, RelativeFileName As String, Optimization As CompressionOption)
            If Not File.Exists(FullFilename) Then
                Throw New FileNotFoundException("AddFileToZip: Error: " & FullFilename)
            End If

            'Create a URI from the filename to zip (to ensure the name is valid)
            Dim fileURI As New Uri(UriFromFilename(RelativeFileName), UriKind.Relative)

            Dim filePart As PackagePart = Zip.CreatePart(fileURI, _
                                                         Net.Mime.MediaTypeNames.Application.Zip, _
                                                         Optimization)
            'Read the file into a byte array to can be written to Zip stream
            Dim arrBuffer As Byte() = File.ReadAllBytes(FullFilename)
            filePart.GetStream().Write(arrBuffer, 0, arrBuffer.Length)
        End Sub



        Private Shared Function UriFromFilename(ByVal FileName As String) As String
            'Replace spaces with underscores
            FileName = FileName.Replace(" "c, "_"c)

            'If a : in second character, then an absolute path, else relative
            Dim relative As Boolean
            If FileName.Length > 2 AndAlso FileName.Substring(1, 1) = ":" Then
                relative = False
            Else
                relative = True
            End If

            'A Uri MUST start with a /
            If Not relative Then
                FileName = String.Concat("/", IO.Path.GetFileName(FileName))
            Else
                FileName = FileName.Replace("\", "/")
                If FileName.StartsWith("/") = False Then FileName = "/" & FileName
            End If

            Return FileName
        End Function

        Public Shared Sub CreateDirectoryPathIfNeeded(FullFilename As String)
            Dim dirName As String = IO.Path.GetDirectoryName(FullFilename)
            If Not IO.Directory.Exists(dirName) Then
                IO.Directory.CreateDirectory(dirName)
            End If
            Return
        End Sub

    End Class



End Namespace